//
//  NSDictionary+MOCrashHandle.m
//  WCImApp
//
//  Created by MOiMac on 2019/12/23.
//  Copyright © 2019 WCImApp. All rights reserved.
//

#import "NSDictionary+MOCrashHandle.h"
#import "NSObject+MOSwizzleMethod.h"
#import <objc/runtime.h>

@implementation NSDictionary (MOCrashHandle)

static NSString *KDictionaryClass = @"__NSPlaceholderDictionary";

+(void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        @autoreleasepool {
            
            [self swizzleClassMethodWithClass:NSClassFromString(KDictionaryClass)
                 originalSel:@selector(initWithObjects:forKeys:count:)
            swizzledSel:@selector(mo_initWithObjects:forKeys:count:)];
            [self swizzleClassMethodWithClass:NSClassFromString(KDictionaryClass)
                 originalSel:@selector(dictionaryWithObjects:forKeys:count:)
            swizzledSel:@selector(mo_dictionaryWithObjects:forKeys:count:)];
        }
    });
}

//字典 类方法的调用，取出所有的key和value来进行比对，安顿是否有为空
+ (instancetype)mo_dictionaryWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        //如果key或value有为空的情况，就跳过去
        if (!key || !obj) {
            /*
             break是结束整个循环，而continue是结束本次循环（跳过下一步），
             为了循环的继续，我们就必须选择continue.
             */
            continue;
        }
        //每一个value对应一个key，这个是相互对应的，详见demo。
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    //处理完毕之后，我们返回新的kay、value以及count，此时我们已经将nil的key&value清除掉了。
    return [self mo_dictionaryWithObjects:safeObjects forKeys:safeKeys count:j];
}

//在这里对数据进行重组，针对数据为空的情况，处理方式同上
- (instancetype)mo_initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt {
    id safeObjects[cnt];
    id safeKeys[cnt];
    NSUInteger j = 0;
    for (NSUInteger i = 0; i < cnt; i++) {
        id key = keys[i];
        id obj = objects[i];
        if (!key || !obj) {
            continue;
        }
        if (!obj) {
            obj = [NSNull null];
        }
        safeKeys[j] = key;
        safeObjects[j] = obj;
        j++;
    }
    return [self mo_initWithObjects:safeObjects forKeys:safeKeys count:j];
}

@end


#pragma mark 设置可变字典的崩溃处理
@implementation NSMutableDictionary (MOCrashHandle)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //获取可变字典的类名。调用方法进行交换
        Class class = NSClassFromString(@"__NSDictionaryM");
        
        [class swizzleMethod:@selector(setObject:forKey:) swizzledSelector:@selector(mo_setObject:forKey:)];
//        [class swizzleMethod:@selector(setObject:forKeyedSubscript:) swizzledSelector:@selector(mo_setObject:forKeyedSubscript:)];

        [class swizzleMethod:@selector(removeObjectForKey:) swizzledSelector:@selector(mo_removeObjectForKey:)];

    });
}

- (void)mo_setObject:(id)anObject forKey:(id<NSCopying>)aKey {

    if (!aKey || !anObject) {
        return;
    }
    [self mo_setObject:anObject forKey:aKey];
}

- (void)mo_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {

    if (!key || !obj) {
        return;
    }
    [self mo_setObject:obj forKeyedSubscript:key];
}

- (void)mo_removeObjectForKey:(id)aKey{
    if (aKey == nil) {
        return;
    }else{
        [self mo_removeObjectForKey:aKey];
    }
}


//@implementation NSMutableDictionary (MOCrashHandle)
//
//
//
//+(void)load {
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        @autoreleasepool {
//            [self swizzleClassMethodWithClass:NSClassFromString(@"__NSDictionaryM") originalSel:@selector(setObject:forKey:) swizzledSel:@selector(mo_setObject:forKey:)];
//            [self swizzleClassMethodWithClass:NSClassFromString(@"__NSDictionaryM") originalSel:@selector(setObject:forKeyedSubscript:) swizzledSel:@selector(mo_setObject:forKeyedSubscript:)];
//        }
//    });
//}
//
//- (void)mo_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
//
//    if (!aKey || !anObject) {
//
//        NSLog(@"遇到为nil的情况，执行一次");
//        return;
//    }
//    [self mo_setObject:anObject forKey:aKey];
//}
//
//- (void)mo_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
//
//    if (!key || !obj) {
//        return;
//    }
//    [self mo_setObject:obj forKeyedSubscript:key];
//}
@end
